#ifndef __SDF_H
#define __SDF_H

//定义设备信息结构
typedef struct DeviceInfo_st
{
    unsigned char IssuerName[40];	//设备生产厂商
    unsigned char DeviceName[16];	//设备型号
    unsigned char DeviceSerial[16]; //设备编号，包含：日期（8字符）、批次号（3字符）、流水号（5字符）
    unsigned int DeviceVersion;		//密码设备软件的版本号
    unsigned int StandardVersion;	//密码设备支持的接口规范版本号
    unsigned int AsymAlgAbility[2]; //前4字节表示支持的算法，表示方法为非对称算法标识按位或的结果;后4字节表示算法的最大模长，表示方法为支持的模长按位或的结果
    unsigned int SymAlgAbility;		//所有支持的对称算法，表示方法为对称算法标识按位或运算结果
    unsigned int HashAlgAbility;	//所有支持的杂凑算法，表示方法为杂凑算法标识按位或运算结果
    unsigned int BufferSize;		//支持的最大文件存储空间（单位字节）
} DEVICEINFO;

//定义RSA密钥数据结构
#define RSAref_MAX_BITS 2048
#define RSAref_MAX_LEN ((RSAref_MAX_BITS + 7) / 8)
#define RSAref_MAX_PBITS ((RSAref_MAX_BITS + 1) / 2)
#define RSAref_MAX_PLEN ((RSAref_MAX_PBITS + 7) / 8)
typedef struct RSArefPublicKey_st
{
    unsigned int bits;
    unsigned char m[RSAref_MAX_LEN];
    unsigned char e[RSAref_MAX_LEN];
} RSArefPublicKey;
typedef struct RSArefPrivateKey_st
{
    unsigned int bits;
    unsigned char m[RSAref_MAX_LEN];
    unsigned char e[RSAref_MAX_LEN];
    unsigned char d[RSAref_MAX_LEN];
    unsigned char prime[2][RSAref_MAX_PLEN];
    unsigned char pexp[2][RSAref_MAX_PLEN];
    unsigned char coef[RSAref_MAX_PLEN];
} RSArefPrivateKey;

//定义ECC密钥数据结构
#define ECCref_MAX_BITS 512
#define ECCref_MAX_LEN ((ECCref_MAX_BITS+ 7 ) / 8)
typedef struct ECCrefPublicKey_st
{
    unsigned int bits;
    unsigned char x[ECCref_MAX_LEN];
    unsigned char y[ECCref_MAX_LEN];
} ECCrefPublicKey;
typedef struct ECCrefPrivateKey_st
{
    unsigned int bits;
    unsigned char K[ECCref_MAX_LEN];
} ECCrefPrivateKey;

//定义ECC加密数据结构
typedef struct ECCCipher_st
{
    unsigned char x[ECCref_MAX_LEN];
    unsigned char y[ECCref_MAX_LEN];
    unsigned char M[32];
    unsigned int L;
    unsigned char C[1];
} ECCCipher;
//定义ECC签名数据结构
typedef struct ECCSignature_st
{
    unsigned char r[ECCref_MAX_LEN];
    unsigned char s[ECCref_MAX_LEN];
} ECCSignature;

typedef UINT8;
typedef UINT32;
typedef UINT32 ULONG;
typedef UINT8 BYTE;
//定义ECC公钥数据结构
#define ECC_MAX_XCOORDINATE_BITS_LEN 512
#define ECC_MAX_YCOORDINATE_BITS_LEN 512
typedef struct Struct_ECCPUBLICKEYBLOB{
ULONG BitLen;
BYTE XCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN/8];
BYTE YCoordinate[ECC_MAX_YCOORDINATE_BITS_LEN/8];
}ECCPUBLICKEYBLOB, * PECCPUBLICKEYBLOB;

//定义ECC密文数据结构
typedef struct Struct_ECCCIPHERBLOB{
BYTE XCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN/8];
BYTE YCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN/8];
BYTE HASH[32];
ULONG CipherLen;
BYTE Cipher[1];
}ECCCIPHERBLOB, * PECCCIPHERBLOB;

//定义ECC加密密钥对保护结构
typedef struct SDF_ENVELOPEDKEYBLOB
{
    unsigned long ulAsymmAlgID;
    unsigned long ulSymmAlgID;
    ECCCIPHERBLOB ECCCipherBlob;
    ECCPUBLICKEYBLOB PubKey;
    unsigned char cbEncryptedPriKey[64];
} ENVELOPEDKEYBLOB, * PENVELOPEDKEYBLOB;

//Error Code
#define SDR_OK  0x0   //操作成功
#define SDR_BASE   0x01000000	//错误码基础值
#define SDR_UNKNOWERR	SDR_BASE + 0x00000001	//未知错误
#define SDR_NOTSUPPORT	SDR_BASE + 0x00000002	//不支持的接口调用
#define SDR_COMMFAIL	SDR_BASE + 0x00000003	//与设备通信失败
#define SDR_HARDFAIL	SDR_BASE + 0x00000004	//运算模块无响应
#define SDR_OPENDEVICE	SDR_BASE + 0x00000005	//打开设备失败
#define SDR_OPENSESSION	SDR_BASE + 0x00000006	//创建会话失败
#define SDR_PARDENY	    SDR_BASE + 0x00000007	//无私钥使用权限
#define SDR_KEYNOTEXIST	SDR_BASE + 0x00000008	//不存在的密钥调用
#define SDR_ALGNOTSUPPORT    SDR_BASE + 0x00000009	//不支持的算法调用
#define SDR_ALGMODNOTSUPPORT SDR_BASE + 0x0000000A	//不支持的算法模式调用
#define SDR_PKOPERR	    SDR_BASE + 0x0000000B	//公钥运算失败
#define SDR_SKOPERR	    SDR_BASE + 0x0000000C	//私钥运算失败
#define SDR_SIGNERR	    SDR_BASE + 0x0000000D	//签名运算失败
#define SDR_VERIFYERR	SDR_BASE + 0x0000000E	//验证签名失败
#define SDR_SYMOPERR	SDR_BASE + 0x0000000F	//对称算法运算失败
#define SDR_STEPERR	    SDR_BASE + 0x00000010	//多步运算步骤错误
#define SDR_FILESIZEERR	SDR_BASE + 0x00000011	//文件长度超出限制
#define SDR_FILENOEXIST	SDR_BASE + 0x00000012	//指定的文件不存在
#define SDR_FILEOFSERR	SDR_BASE + 0x00000013	//文件起始位置错误
#define SDR_KEYTYPEERR	SDR_BASE + 0x00000014	//密钥类型错误
#define SDR_KEYERR	    SDR BASE + 0x00000015   //密钥错误
#define SDR_ENCDATAERR	SDR_BASE + 0x00000016	//ECC加密数据错误
#define SDR_RANDERR	SDR_BASE + 0x00000017	//随机数产生失败
#define SDR_PRKRERR	SDR_BASE + 0x00000018	//私钥使用权限获取失败
#define SDR_MACERR	    SDR_BASE + 0x00000019   //MAC运算失败
#define SDR_FILEEXISTS	SDR_BASE + 0x0000001A	//指定文件已存在
#define SDR_FILEWERR	SDR_BASE + 0x0000001B	//文件写入失败
#define SDR_NOBUFFER	SDR_BASE + 0x0000001C	//存储空间不足
#define SDR_INARGERR	SDR_BASE + 0x0000001D	//输入参数错误
#define SDR_OUTARGERR	SDR_BASE + 0x0000001E	//输出参数错误
//SDR_BASE + 0x0000001F至SDR_BASE + 0x00FFFFFF	预留

//*********************************
//设备管理
//*********************************

/*
功能：打开密码设备
参数：phDeviceHandle[out] 返回设备句柄
返回值：0 成功
        非0 失败,返回错误代码
*/
int SDF_OpenDevice(void ** phDeviceHandle);

/*
功能：关闭密码设备，并释放相关资源
参数：hDeviceHandle[in] 已打开的设备句柄
返回值：0 成功
        非0 失败,返回错误代码
*/
int SDF_CloseDevice(void * hDeviceHandle);

/*
功能：获取设备信息
参数：hSessionHandle[in] 与设备建立的会话句柄
      pstDeviceInfo[out] 设备能力描述信息，内容及格式见设备信息定义
返回值：0 成功
        非0 失败,返回错误代码
*/
int SDF_GetDeviceInfo(void * hSessionHandle,DEVICEINFO * pstDeviceInfo);

/*
功能：获取指定长度的随机数
参数：hSessionHandle[in] 与设备建立的会话句柄
      uiLength[in]       欲获取的随机数长度
      pucRandom[out]     缓冲区指针，用于存放获取的随机数
返回值：0 成功
        非0 失败,返回错误代码
*/
int SDF_GenerateRandom (void * hSessionHandle, unsigned int uiLength,unsigned char * pucRandom);

/*
功能：导出密码设备内部存储的指定索引位置的签名公钥
参数：hSessionHandle[in] 与设备建立的会话句柄
      uiKeyIndex[in]     密码设备存储的ECC密钥对索引值
      pucPublicKey[out]  ECC公钥结构
返回值：0 成功
        非0 失败,返回错误代码
*/
int SDF_ExportSignPublicKey_ECC(void * hSessionHandle,unsigned int uiKeyIndex,ECCrefPublicKey * pucPublicKey);

/*
功能：导出密码设备内部存储的指定索引位置的加密公钥
参数：hSessionHandle[in] 与设备建立的会话句柄
      uiKeyIndex[in]     密码设备存储的ECC密钥对索引值
      pucPublicKey[out]  ECC公钥结构
返回值：0 成功
        非0 失败,返回错误代码
*/
int SDF_ExportEncPublicKey_ECC(void * hSessionHandle,unsigned int uiKeyIndex,ECCrefPublicKey * pucPublicKey);

/*
功能：请求密码设备产生指定类型和模长的ECC密钥对
参数：hSessionHandle[in] 与设备建立的会话句柄
      uiAlgID[in]        指定算法标识
      uiKeyBits[in]      指定密钥长度
      pucPublicKey[out]  ECC公钥结构
      pucPrivateKey[out] ECC私钥结构
返回值：0 成功
        非0 失败,返回错误代码
*/
int SDF_GenerateKeyPair_ECC( void * hSessionHandle,unsigned int uiAlgID,unsigned int uiKeyBits, ECCrefPublicKey * pucPublicKey,ECCrefPrivateKey * pucPrivateKey);

/*
功能：使用外部ECC公钥对ECC签名值进行验证运算
参数：hSessionHandle[in] 与设备建立的会话句柄
      uiAlgID[in]        算法标识，指定使用的ECC算法
      pucPublicKey[in]   外部ECC公钥结构
      pucData[in]        缓冲区指针，用于存放外部输入的数据
      uiDataLength[in]   输入的数据长度
      pucSignature[in]   缓冲区指针,用于存放输入的签名值数据
返回值：0 成功
        非0 失败,返回错误代码
备注：输入数据为待签数据的杂凑值。当使用SM2算法时，该输入数据为待签数据经过SM2签名预处理的结果,预处理过程见GM/T 0009。
*/
int SDF_ExternalVerify_ECC(void * hSessionHandle,unsigned int uiAlgID,ECCrefPublicKey * pucPublicKey, unsigned char * pucDataInput, unsigned int uiInputLength, ECCSignature * pucSignature);

/*
功能：使用内部ECC私钥对数据进行签名运算
参数：hSessionHandle[in] 与设备建立的会话句柄
      uiISKIndex[in]     密码设备内部存储的ECC签名私钥的索引值
      pucData[in]        缓冲区指针，用于存放外部输入的数据
      uiDataLength[in]   输入的数据长度
      pucSignature[out]  缓冲区指针,用于存放输入的签名值数据
返回值：0 成功
        非0 失败,返回错误代码
备注：输入数据为待签数据的杂凑值。当使用SM2算法时，该输入数据为待签数据经过SM2签名预处理的结果,预处理过程见GM/T 0009。
*/
int SDFInternalSign_ECC(void * hSessionHandle, unsigned int uiISKIndex, unsigned char * pucData,unsigned int uiDataLength, ECCSignature * pucSignature);

/*
功能：使用内部ECC公钥对ECC签名值进行验证运算
参数：hSessionHandle[in] 与设备建立的会话句柄
      uiISKIndex[in]    密码设备内部存储的ECC签名私钥的索引值
      pucData[in]        缓冲区指针，用于存放外部输入的数据
      uiDataLength[in]   输入的数据长度
      pucSignature[out]  缓冲区指针,用于存放输入的签名值数据
返回值：0 成功
        非0 失败,返回错误代码
备注：输入数据为待签数据的杂凑值。当使用SM2算法时，该输入数据为待签数据经过SM2签名预处理的结果,预处理过程见GM/T 0009。
*/
int SDF_InternalVerify_ECC(void * hSessionHandle,unsigned int uiISKIndex,unsigned char * pucData,unsigned int uiDataLength, ECCSignature * pucSignature);

/*
功能：使用外部ECC公钥对数据进行加密运算
参数：hSessionHandle[in] 与设备建立的会话句柄
      uiAlgID[in]        算法标识，指定使用的ECC算法
      pucPublicKey[in]   外部ECC公钥结构
      pucData[in]        缓冲区指针，用于存放外部输入的数据
      uiDataLength[in]   输入的数据长度
      pucEncData[out]    缓冲区指针，用于存放输出的数据密文
返回值：0 成功
        非0 失败,返回错误代码
*/
int SDF_ExternalEncrypt_ECC(void * hSessionHandle, unsigned int uiAlgID,ECCrefPublicKey * pucPublicKey, unsigned char * pucData, unsigned int uiDataLength, ECCCipher * pucEncData);

/*
功能：使用指定的密钥句柄和IV对数据进行对称加密运算
参数：hSessionHandle[in]    与设备建立的会话句柄
      hKeyHandle[in]        指定的密钥句柄
      uiAlgID[in]           算法标识,指定对称加密算法
      pucIV[in|out]         缓冲区指针，用于存放输入和返回的IV数据
      pucData[in]           缓冲区指针，用于存放输入的数据明文
      uiDataLength[in]      输入的数据明文长度
      pucEncData[out]       缓冲区指针，用于存放输出的数据密文
      puiEncDataLength[out] 输出的数据密文长度
返回值：0 成功
        非0 失败,返回错误代码
备注：此函数不对数据进行填充处理,输入的数据必须是指定算法分组长度的整数倍
*/
int SDF_Encrypt(void * hSessionHandle,void * hKeyHandle,unsigned int uiAlgID, unsigned char * pucIV, unsigned char * pucData, unsigned int uiDataLength , unsigned char * pucEncData,unsigned int * puiEncDataLength);

/*
功能：使用指定的密钥句柄和IV对数据进行对称解密运算
参数：hSessionHandle[in]    与设备建立的会话句柄
      hKeyHandle[in]        指定的密钥句柄
      uiAlgID[in]           算法标识,指定对称加密算法
      pucIV[in|out]         缓冲区指针，用于存放输入和返回的IV数据
      pucEncData[in]        缓冲区指针，用于存放输入的数据明文
      uiEncDataLength[in]   输入的数据明文长度
      pucData[out]          缓冲区指针，用于存放输出的数据密文
      puiDataLength[out]    输出的数据密文长度
返回值：0 成功
        非0 失败,返回错误代码
备注：此函数不对数据进行填充处理,输入的数据必须是指定算法分组长度的整数倍
*/
int SDF_Decrypt (void * hSessionHandle, void * hKeyHandle, unsigned int uiAlgID, unsigned char * pucIV,unsigned char * pucEncData, unsigned int uiEncDataLength, unsigned char * pucData, unsigned int * puiDataLength);

/*
功能：使用指定的密钥句柄和IV对数据进行MAC运算
参数：hSessionHandle[in]    与设备建立的会话句柄
      hKeyHandle[in]        指定的密钥句柄
      uiAlgID[in]           算法标识,指定对称加密算法
      pucIV[in|out]         缓冲区指针，用于存放输入和返回的IV数据
      pucData[in]           缓冲区指针，用于存放输出的数据明文
      uiDataLength[in]      输入的数据明文长度
      pucMAC[out]           缓冲区指针，用于存放输出的MAC值
      puiMACLength[out]     输出的MAC值长度
返回值：0 成功
        非0 失败,返回错误代码
备注：此函数不对数据进行分包处理，多包数据MAC运算由IV控制最后的MAC值
*/
int SDF_CalculateMAC(void * hSessionHandle,void * hKeyHandle, unsigned int uiAlgID, unsigned char * pucIV, unsigned char * pucData, unsigned int uiDataLength ,unsigned char * pucMAC, unsigned int * puiMACLength);

/*
功能：三步式数据杂凑运算第一步,杂凑运算初始化
参数：hSessionHandle[in] 与设备建立的会话句柄
      uiAlgID[in]        指定杂凑算法标识
      pucPublicKey[in]   签名者公钥。当uiAlgID为SGD_SM3时有效。
      pucID[in]          签名者的ID值,当uiAlgID为SGD_SM3时有效。
      uiIDLength[in]     签名者ID的长度,当uiAlgID为SGD.SM3时有效。
返回值：0 成功
        非0 失败,返回错误代码
备注：uiIDLength非零且uiAlgID为SGD_SM3时，函数执行SM2的预处理1操作。计算过程见GM/T 0009。
*/
int SDF_HashInit(void * hSessionHandle, unsigned int uiAlgID,ECCrefPublicKey * pucPublicKey,unsigned char * pucID, unsigned int uiIDLength);

/*
功能：三步式数据杂凑运算第二步，对输入的明文进行杂凑运算
参数：hSessionHandle[in] 与设备建立的会话句柄
      pucData[in]        缓冲区指针，用于存放输入的数据明文
      uiDataLength[in]   输入的数据明文长度
返回值：0 成功
        非0 失败,返回错误代码
*/
int SDF_HashUpdate(void * hSessionHandle,unsigned char * pucData,unsigned int uiDataLength);

/*
功能：三步式数据杂凑运算第三步，杂凑运算结束返回杂凑数据并清除中间数据
参数：hSessionHandle[in] 与设备建立的会话句柄
      pucHash[out]       缓冲区指针，用于存放输出的杂凑数据
      puiHashLength[out] 返回的杂凑数据长度
返回值：0 成功
        非0 失败,返回错误代码
*/
int SDF_HashFinal (void * hSessionHandle,unsigned char * pucHash,unsigned int * puiHashLength);

#endif
